package com.gitee.apanlh.util.base;

import com.gitee.apanlh.util.func.FuncFor;
import com.gitee.apanlh.util.func.FuncIterator;
import com.gitee.apanlh.util.func.FuncIterator2;
import com.gitee.apanlh.util.func.FuncIteratorBreak;
import com.gitee.apanlh.util.func.FuncIteratorBreak2;
import com.gitee.apanlh.util.func.FuncIteratorE;
import com.gitee.apanlh.util.func.FuncIteratorEBreak;
import com.gitee.apanlh.util.func.FuncIteratorK;
import com.gitee.apanlh.util.func.FuncIteratorK2;
import com.gitee.apanlh.util.func.FuncIteratorKBreak;
import com.gitee.apanlh.util.func.FuncIteratorResultE;
import com.gitee.apanlh.util.func.FuncIteratorV;
import com.gitee.apanlh.util.func.FuncIteratorV2;
import com.gitee.apanlh.util.func.FuncIteratorVBreak;
import com.gitee.apanlh.util.func.FuncLoop;
import com.gitee.apanlh.util.func.FuncLoopIndex;

import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/**	
 * 	迭代器
 * 
 * 	@author Pan
 */
public class IteratorUtils {
	
	/**
	 * 	构造函数
	 * 
	 * 	@author Pan
	 */
	private IteratorUtils() {
		//	不允许外部实例
		super();
	}

	/**
	 * 	重复循环遍历
	 * 	<br>func返回true时，将重复循环(如果遍历至最后一个索引后将从0开始重复遍历）
	 * 	<br>func返回false时，将停止循环
	 *
	 * 	@author Pan
	 * 	@param  <T>      数据类型
	 * 	@param 	list	 集合
	 * 	@param 	func loop函数
	 */
	public static <T> void repeatLoop(List<T> list, FuncLoop<T> func) {
		if (list == null) {
			return ;
		}

		int index = 0;
		int size = list.size();
		while (index < size) {
			boolean next = func.get(list.get(index));
			if (!next) {
				break;
			}
			index = CollUtils.isLastIndex(list, index) ? 0 : index + 1;
		}
	}

	/**
	 * 	重复循环遍历-额外返回当前索引标识
	 * 	<br>funcLoop返回true时，将重复循环(如果遍历至最后一个索引后将从0开始重复遍历）
	 * 	<br>funcLoop返回false时，将停止循环
	 *
	 * 	@author Pan
	 * 	@param  <T>      		数据类型
	 * 	@param 	list	 		集合
	 * 	@param 	func 			loop函数
	 */
	public static <T> void repeatLoop(List<T> list, FuncLoopIndex<T> func) {
		if (list == null) {
			return ;
		}

		int index = 0;
		int size = list.size();
		while (index < size) {
			boolean next = func.get(list.get(index), index);
			if (!next) {
				break;
			}
			index = CollUtils.isLastIndex(list, index) ? 0 : index + 1;
		}
	}

	/**
	 * 	循环遍历
	 * 	
	 * 	@author Pan
	 * 	@param  <T>      数据类型
	 * 	@param 	array	 数组
	 * 	@param 	func	 for函数
	 */
	public static <T> void array(T[] array, FuncFor<T> func) {
		if (array == null) {
			return ;
		}
		for (int i = 0, len = array.length; i < len; i++) {
			func.get(array[i]);
		}
	}
	
	/**
	 * 	循环遍历
	 * 	
	 * 	@author Pan
	 * 	@param  <T>      数据类型
	 * 	@param 	array	 数组
	 * 	@param 	func	 for函数
	 */
	public static <T> void array(List<T> array, FuncFor<T> func) {
		if (array == null) {
			return ;
		}
		for (int i = 0, len = array.size(); i < len; i++) {
			func.get(array.get(i));
		}
	}
	
	/**
	 * 	循环遍历
	 * 	
	 * 	@author Pan
	 * 	@param  <E>      	数据类型
	 * 	@param 	enumeration	枚举
	 * 	@param 	func		迭代函数
	 */
	public static <E> void array(Enumeration<E> enumeration, FuncFor<E> func) {
		if (enumeration == null) {
			return ;
		}
		while (enumeration.hasMoreElements()) {
			func.get(enumeration.nextElement());
		}
	}
	
	/**	
	 * 	获取指定元素
	 * 	<br>索引从0开始计算
	 * 
	 * 	@author Pan
	 * 	@param  <E>      	数据类型
	 * 	@param 	collection	集合
	 * 	@param 	index		索引
	 * 	@return	E
	 */
	public static <E> E getElement(Collection<E> collection, int index) {
		if (collection == null || index < 0) {
			return null;
		}
		int collectionSize = collection.size();
		if (collectionSize == 0 || index > collectionSize) {
			return null;
		}
		
		int currentIndex = 0;
		if (currentIndex == index) {
			return collection(collection).next();
		}
		
		E e = null;
		Iterator<E> iterator = collection(collection);
		while (iterator.hasNext()) {
			E e2 = iterator.next();
			if (currentIndex == index) {
				e = e2;
				break;
			}
			currentIndex ++;
		}
		return e;
	} 
	
	/**	
	 * 	获取首位元素
	 * 	
	 * 	@author Pan
	 * 	@param  <E>      	数据类型
	 * 	@param 	collection	集合
	 * 	@return E
	 */
	public static <E> E getFirst(Collection<E> collection) {
		if (collection == null) {
			return null;
		}
		return getElement(collection, 0);
	} 
	
	/**	
	 * 	获取最后元素
	 * 	
	 * 	@author Pan
	 * 	@param  <E>      	数据类型
	 * 	@param 	collection 	集合
	 * 	@return E
	 */
	public static <E> E getLast(Collection<E> collection) {
		if (collection == null) {
			return null;
		}
		return getElement(collection, collection.size() - 1);
	} 
	
	/**	
	 * 	集合迭代器
	 * 	
	 * 	@author Pan
	 * 	@param  <E>      	数据类型
	 * 	@param 	collection 	集合
	 * 	@return E
	 */
	public static <E> Iterator<E> collection(Collection<E> collection) {
		return collection.iterator();
	}
	
	/**	
	 * 	集合迭代器
	 * 	<br>无返回值 提供next方法及返回iterator
	 * 	
	 * 	@author Pan
	 * 	@param  <E>      		数据类型
	 * 	@param 	collection		集合
	 * 	@param 	funcIteratorE	迭代函数
	 */
	public static <E> void collection(Collection<E> collection, FuncIteratorE<E> funcIteratorE) {
		if (collection == null) {
			return ;
		}
		iterator(collection(collection), funcIteratorE);
	}
	
	/**	
	 * 	集合迭代器
	 * 	<br>无返回值 提供next方法及返回iterator
	 * 	
	 * 	@author Pan
	 * 	@param  <E>      			数据类型
	 * 	@param 	collection			集合
	 * 	@param 	funcIteratorBreak	迭代函数(可停止)
	 */
	public static <E> void collectionBreak(Collection<E> collection, FuncIteratorEBreak<E> funcIteratorBreak) {
		if (collection == null) {
			return ;
		}
		iteratorBreak(collection(collection), funcIteratorBreak);
	}
	
	/**	
	 * 	集合迭代器
	 * 	<br>增加返回值
	 * 	
	 * 	@author Pan
	 * 	@param  <E>      			数据类型
	 * 	@param  <R>      			返回类型
	 * 	@param 	collection			集合
	 * 	@param 	func				迭代函数(可返回结果)
	 * 	@return R
	 */
	public static <E, R> R collectionResult(Collection<E> collection, FuncIteratorResultE<E, R> func) {
		iteratorBreak(collection(collection), func::next);
		return func.call();
	}
	
	/**	
	 * 	MapEntrySet迭代器
	 * 	
	 * 	@author Pan
	 *  @param  <K>     键类型
	 *  @param  <V>     值类型
	 * 	@param 	map		map
	 *  @return Iterator
	 */
	public static <K, V> Iterator<Entry<K, V>> entrySet(Map<K, V> map) {
		if (map == null) {
			return null;
		}
		return map.entrySet().iterator();
	}
	
	/**	
	 * 	MapEntrySet迭代器
	 * 	<br>包含迭代器
	 * 	
	 * 	@author Pan
	 *  @param  <K>     键类型
	 *  @param  <V>     值类型
	 * 	@param 	map		map
	 * 	@param 	func	迭代函数
	 */
	public static <K, V> void entrySet(Map<K, V> map, FuncIterator<K, V> func) {
		if (map == null) {
			return ;
		}
		iterator(entrySet(map), func);
	}
	
	/**	
	 * 	MapEntrySet迭代器
	 * 	<br>不包含迭代器
	 * 
	 * 	@author Pan
	 *  @param  <K>     键类型
	 *  @param  <V>     值类型
	 * 	@param 	map		map
	 * 	@param 	func	迭代函数
	 */
	public static <K, V> void entrySet(Map<K, V> map, FuncIterator2<K, V> func) {
		if (map == null) {
			return ;
		}
		iterator(entrySet(map), func);
	}
	
	/**	
	 * 	MapEntrySet迭代器
	 * 	
	 * 	@author Pan
	 *  @param  <K>     键类型
	 *  @param  <V>     值类型
	 * 	@param 	map		map
	 * 	@param 	func	迭代函数
	 */
	public static <K, V> void entrySetBreak(Map<K, V> map, FuncIteratorBreak<K, V> func) {
		if (map == null) {
			return ;
		}
		iteratorBreak(entrySet(map), func);
	}
	
	/**	
	 * 	MapEntrySet迭代器
	 *
	 * 	@author Pan
	 *  @param  <K>     键类型
	 *  @param  <V>     值类型
	 * 	@param 	map		map
	 * 	@param 	func	迭代函数
	 */
	public static <K, V> void entrySetBreak(Map<K, V> map, FuncIteratorBreak2<K, V> func) {
		if (map == null) {
			return ;
		}
		iteratorBreak(entrySet(map), func);
	}
	
	/**	
	 * 	KeySet迭代器
	 * 	
	 * 	@author Pan
	 *  @param  <K>     键类型
	 *  @param  <V>     值类型
	 * 	@param 	map		map
	 * 	@return	Iterator
	 */
	public static <K, V> Iterator<K> keySet(Map<K, V> map) {
		if (map == null) {
			return null;
		}
		return map.keySet().iterator();
	}
	
	/**	
	 * 	KeySet迭代器
	 * 	
	 * 	@author Pan
	 *  @param  <K>     键类型
	 *  @param  <V>     值类型
	 * 	@param 	map		map
	 * 	@param 	func	迭代函数
	 */
	public static <K, V> void keySet(Map<K, V> map, FuncIteratorK<K> func) {
		if (map == null) {
			return ;
		}
		iterator(keySet(map), func::next);
	}
	
	/**	
	 * 	KeySet迭代器(不包含迭代器)
	 * 	
	 * 	@author Pan
	 *  @param  <K>     键类型
	 *  @param  <V>     值类型
	 * 	@param 	map		map
	 * 	@param 	func	迭代函数
	 */
	public static <K, V> void keySet(Map<K, V> map, FuncIteratorK2<K> func) {
		if (map == null) {
			return ;
		}
		iterator(keySet(map), func::next);
	}
	
	/**	
	 * 	KeySet迭代器
	 * 	
	 * 	@author Pan
	 *  @param  <K>     键类型
	 *  @param  <V>     值类型
	 * 	@param 	map		map
	 * 	@param 	func	迭代函数
	 */
	public static <K, V> void keySetBreak(Map<K, V> map, FuncIteratorKBreak<K> func) {
		if (map == null) {
			return ;
		}
		iterator(keySet(map), func::next);
	}
	
	/**	
	 * 	Map集合迭代器
	 * 	
	 * 	@author Pan
	 *  @param  <K>     键类型
	 *  @param  <V>     值类型
	 * 	@param 	map		map
	 * 	@return	Iterator
	 */
	public static <K, V> Iterator<V> values(Map<K, V> map) {
		if (map == null) {
			return null;
		}
		return collection(map.values());
	}
	
	/**	
	 * 	Map集合迭代器
	 * 	<br>不包含迭代器
	 * 	
	 * 	@author Pan
	 *  @param  <K>     键类型
	 *  @param  <V>     值类型
	 * 	@param 	map		map
	 * 	@param 	func	迭代函数
	 */
	public static <K, V> void values(Map<K, V> map, FuncIteratorV<V> func) {
		if (map == null) {
			return ;
		}
		iterator(collection(map.values()), func::next);
	}
	
	/**	
	 * 	Map集合迭代器
	 * 	<br>包含迭代器
	 * 	
	 * 	@author Pan
	 *  @param  <K>     键类型
	 *  @param  <V>     值类型
	 * 	@param 	map		map
	 * 	@param 	func	迭代函数
	 */
	public static <K, V> void values(Map<K, V> map, FuncIteratorV2<V> func) {
		if (map == null) {
			return ;
		}
		iterator(collection(map.values()), func::next);
	}
	
	/**	
	 * 	Map集合迭代器
	 * 	
	 * 	@author Pan
	 *  @param  <K>     键类型
	 *  @param  <V>     值类型
	 * 	@param 	map		map
	 * 	@param 	func	迭代函数
	 */
	public static <K, V> void valuesBreak(Map<K, V> map, FuncIteratorVBreak<V> func) {
		if (map == null) {
			return ;
		}
		iterator(collection(map.values()), func::next);
	}
	
	/**
	 * 	迭代器
	 * 	
	 * 	@author Pan
	 * 	@param  <E>      	数据类型
	 * 	@param 	iterator	迭代器
	 * 	@param 	func		迭代函数
	 */
	public static <E> void iterator(Iterator<E> iterator, FuncFor<E> func) {
		if (iterator == null) {
			return ;
		}
		while (iterator.hasNext()) {
			func.get(iterator.next());
		}
	}
	
	/**
	 * 	迭代器
	 * 	
	 * 	@author Pan
	 * 	@param  <E>      	 数据类型
	 * 	@param 	iterator	 迭代器
	 * 	@param 	func 		 迭代函数
	 */
	public static <E> void iterator(Iterator<E> iterator, FuncIteratorE<E> func) {
		if (iterator == null) {
			return ;
		}
		while (iterator.hasNext()) {
			func.next(iterator.next(), iterator);
		}
	}
	
	/**
	 * 	迭代器
	 * 	
	 * 	@author Pan
	 * 	@param  <E>      	 数据类型
	 * 	@param 	iterator	 迭代器
	 * 	@param 	func 		 迭代函数
	 */
	public static <E> void iteratorBreak(Iterator<E> iterator, FuncIteratorEBreak<E> func) {
		if (iterator == null) {
			return ;
		}
		while (iterator.hasNext()) {
			if (!func.next(iterator.next(), iterator)) {
				break;
			}
		}
	}
	
	/**
	 * 	迭代器
	 * 	
	 * 	@author Pan
	 *  @param  <K>     		键类型
	 *  @param  <V>     		值类型
	 * 	@param 	iterator	 	迭代器
	 * 	@param 	func 			迭代函数
	 */
	public static <K, V> void iterator(Iterator<Entry<K, V>> iterator, FuncIterator<K, V> func) {
		if (iterator == null) {
			return ;
		}
		while (iterator.hasNext()) {
			Entry<K, V> next = iterator.next();
			func.next(next.getKey(), next.getValue(), iterator);
		}
	}
	
	/**
	 * 	迭代器
	 * 	
	 * 	@author Pan
	 *  @param  <K>     		键类型
	 *  @param  <V>     		值类型
	 * 	@param 	iterator	 	迭代器
	 * 	@param 	func 			迭代函数
	 */
	public static <K, V> void iterator(Iterator<Entry<K, V>> iterator, FuncIterator2<K, V> func) {
		if (iterator == null) {
			return ;
		}
		while (iterator.hasNext()) {
			Entry<K, V> next = iterator.next();
			func.next(next.getKey(), next.getValue());
		}
	}
	
	/**
	 * 	迭代器
	 * 	
	 * 	@author Pan
	 *  @param  <K>     		键类型
	 *  @param  <V>     		值类型
	 * 	@param 	iterator	 	迭代器
	 * 	@param 	func 			迭代函数
	 */
	public static <K, V> void iteratorBreak(Iterator<Entry<K, V>> iterator, FuncIteratorBreak<K, V> func) {
		if (iterator == null) {
			return ;
		}
		while (iterator.hasNext()) {
			Entry<K, V> next = iterator.next();
			if (!func.next(next.getKey(), next.getValue(), iterator)) {
				break;
			}
		}
	}
	
	/**
	 * 	迭代器
	 * 	<br>迭代是可中断迭代
	 * 	<br>true则继续 false则终止
	 * 	
	 * 	@author Pan
	 *  @param  <K>     		键类型
	 *  @param  <V>     		值类型
	 * 	@param 	iterator	 	迭代器
	 * 	@param 	func 			迭代函数
	 */
	public static <K, V> void iteratorBreak(Iterator<Entry<K, V>> iterator, FuncIteratorBreak2<K, V> func) {
		if (iterator == null) {
			return ;
		}
		while (iterator.hasNext()) {
			Entry<K, V> next = iterator.next();
			if (!func.next(next.getKey(), next.getValue())) {
				break;
			}
		}
	}
}
